﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using BbsbWebService.Classes;
using BbsbWebService.Enums;
using BbsbWebService.Repositories;
using System.Collections.ObjectModel;
using System.Reflection;
using BbsbWebService.Classes.Plugins.KeyMap;
using BbsbWsGui;

namespace BbsbWebService
{
    /// <summary>
    /// Interaction logic for AddItemWindow.xaml
    /// </summary>
    public partial class AddItemWindow : Window
    {
        #region Private Members

        List<Group> allGroupsList;
        List<Group> memberGroupsList;
        private Guid _initialId;
        private Type _currentType;
        ControllableItem _originalItem;

        #endregion

        public AddItemWindow(ControllableItem item)
        {
            InitializeComponent();
            _initialId = item.Id;
            _originalItem = item;
            itemTypeCbo.SelectedItem = item.TypeName;
            commandTxt.Text = item.Command;
            nameTxt.Text = item.Name;
            memberGroups.ItemsSource = item.Groups;
            isImportantChk.IsChecked = item.IsImportant;
            toggleItemChk.IsChecked = item.IsAlwaysStateAware;
            allGroupsList = new List<Group>(item.NotGroups);
            memberGroupsList = new List<Group>(item.Groups);
            Init();
            SetAdditionalPanel();
        }

        public AddItemWindow()
        {
            InitializeComponent();
            _initialId = Guid.NewGuid();
            isImportantChk.IsChecked = false;
            toggleItemChk.IsChecked = true;
            allGroupsList = new List<Group>(RepositoryInstances.GroupRepository.Items);
            memberGroupsList = new List<Group>();
            Init();
            itemTypeCbo.SelectedIndex = 0;
            SetAdditionalPanel();
        }

        private void Init()
        {
            List<string> types = new List<string>();
            foreach (var itemType in AppSettings.ItemTypeDictionary)
            {
                types.Add(itemType.Key);
            }
            itemTypeCbo.ItemsSource = types;
            Refresh();
        }

        public ControllableItem Item { get; set; }

        private void saveBtn_Click(object sender, RoutedEventArgs e)
        {
            // Add drop down for item type
            string type = itemTypeCbo.Text;
            ControllableItem item = ControllableItemFactory.CreateItem(type);
            if (item != null)
            {
                item.Id = _initialId;

                item.Command = commandTxt.Text;
                item.Name = nameTxt.Text;

                List<Group> groups = memberGroups.ItemsSource as List<Group>;
                if (groups != null)
                {
                    item.Groups = groups;
                }

                item.IsAlwaysStateAware = (toggleItemChk.IsChecked == true);
                item.IsImportant = isImportantChk.IsChecked == true;

                // Get additional parameters...
                string additionalErrors = string.Empty;
                foreach (var propItem in additionalPropertiesGrid.Items)
                {
                    Prop bob = propItem as Prop;
                    if (bob != null)
                    {
                        try
                        {
                            if (bob.TrySetValueAsType())
                            {
                                PropertyInfo info = bob.GetOriginal();
                                info.SetValue(item, bob.Value, null);
                            }
                            else
                            {
                                throw new InvalidCastException();
                            }
                        }
                        catch (Exception ex)
                        {
                            additionalErrors += string.Format("Invalid value, cannot parse {0} as {1} for field {2}. {3}\r\n", bob.Value, bob.Type, bob.Name, ex.Message);
                        }
                    }
                }

                var state = item.ValidationState;
                if (additionalErrors.IsNullOrEmpty() && state.IsValid)
                {
                    Item = item;
                    this.DialogResult = true;
                    this.Close();
                }
                else
                {
                    MessageBox.Show(additionalErrors + state.ToString());
                }
            }
        }

        private void joinGroup_Click(object sender, RoutedEventArgs e)
        {
            if (allGroups.SelectedItems != null)
            {
                foreach (var obj in allGroups.SelectedItems)
                {
                    Group group = obj as Group;
                    if (group != null)
                    {
                        memberGroupsList.Add(group);
                        allGroupsList.Remove(group);
                    }
                }
            }
            Refresh();
        }

        private void removeGroup_Click(object sender, RoutedEventArgs e)
        {
            if (memberGroups.SelectedItem != null)
            {
                Group group = memberGroups.SelectedItem as Group;
                if (group != null)
                {
                    allGroupsList.Add(group);
                    memberGroupsList.Remove(group);
                    Refresh();
                }
            }
        }

        private void newGroupBtn_Click(object sender, RoutedEventArgs e)
        {
            NewGroup window = new NewGroup();
            if (window.ShowDialog() == true &&
                window.Group != null)
            {
                RepositoryInstances.GroupRepository.SaveItem(window.Group);
                allGroupsList.Add(window.Group);
                Refresh();
            }
        }

        private void cancelBtn_Click(object sender, RoutedEventArgs e)
        {
            Item = null;
            this.Close();
        }

        private void Refresh()
        {
            allGroups.ItemsSource = allGroupsList;
            allGroups.Items.Refresh();
            memberGroups.ItemsSource = memberGroupsList;
            memberGroups.Items.Refresh();
        }

        private void isImportantChk_Checked(object sender, RoutedEventArgs e)
        {

        }

        private void itemTypeCbo_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            SetAdditionalPanel();
        }

        private void SetAdditionalPanel()
        {
            string typeName = itemTypeCbo.SelectedItem.ToString();
            if (AppSettings.ItemTypeDictionary.ContainsKey(typeName))
            {
                _currentType = AppSettings.ItemTypeDictionary[typeName];
                List<Prop> additionalProperties = new List<Prop>();
                var allProps = _currentType.GetProperties();
                var props = allProps.Where(o => o.DeclaringType == _currentType);
                foreach (var prop in props)
                {
                    if (prop.GetCustomAttributes(typeof(System.Runtime.Serialization.DataMemberAttribute), true).Length > 0)
                    {
                        if (_originalItem == null)
                            _originalItem = ControllableItemFactory.CreateItem(typeName);
                        additionalProperties.Add(new Prop(prop) { Value = prop.GetValue(_originalItem, null) });
                    }
                }

                if (props.Any())
                {
                    additionalPropertiesGrid.Visibility = System.Windows.Visibility.Visible;
                    additionalPropertiesGrid.ItemsSource = additionalProperties;
                }
                else
                {
                    additionalPropertiesGrid.Visibility = System.Windows.Visibility.Collapsed;
                }
            }
        }
    }
}
